package proto;

import java.awt.Color;


/**
 * @author Bitjaeger
 *
 */
public class Stickman {
    private int keysCollected;
    private Point position;
    private Point revivePosition;
    private Field field;
    private Color color;

    public Stickman(Point position, Color c) {
        this.position = revivePosition = position;
        field = position.tile.GetField(position);
        keysCollected = 0;
        color = c;
    }

    /**
    * Stickman tries to move to a given direction.
    *
    * First test if it's at the edge of the current tile.
    * If so, invoke the MoveThroughEdge method.
    * Otherwise test if the field in the given direction is a brick.
    * If not, it can step into the field, modify its position and
    * let the new field perform the appropriate action.
    *
    * @param direction
    */
    public boolean Move(Direction direction) {
        //No jumping if we're not on the ground
        if(direction == Direction.UP &&
            (field.GetNeighbor(Direction.DOWN) == null ||
            field.GetNeighbor(Direction.DOWN).CanICome()))
        {
            return false;
        }
        if (field.GetNeighbor(direction) == null){
            // Stickman is trying to move off the tile
            return MoveThroughEdge(direction);
        }else if (field.GetNeighbor(direction).CanICome()) {
            field.Leave();
            field = field.GetNeighbor(direction);
            position = field.GetPosition();
            field.DoAction(this);
            return true;
        }
        return false;
    }

    /**
    * Stickman tries to pass through an edge of the current tile.
    *
    * First it must ask the tile if it can do that.
    * If the response is yes, it passes through and modifies its variables approprietly.
    * If not, it either doesn't move at all (horizontal movement)
    * or dies (fall).
    */
    public boolean MoveThroughEdge(Direction direction) {
        Tile neighbor;
        Field oldField;
        if(position.tile.MayIGoInDirection(direction)){
            oldField = field;
            // find out which Tile stickman goes to
            neighbor = position.tile.GetNeighbor(direction);
            // find out which Field stickman goes to
            switch(direction){
                case LEFT :
                    field = neighbor.GetField(new Point(null, position.tile.GetColumnCount()-1, position.y));
                    break;
                case RIGHT:
                    field = neighbor.GetField(new Point(null, 0, position.y));
                    break;
                case UP:
                    field = neighbor.GetField(new Point(null, position.x, position.tile.GetRowCount()-1));
                    break;
                case DOWN:
                    field = neighbor.GetField(new Point(null, position.x, 0));
                    break;
            }
            if(field.CanICome()){
                oldField.Leave();
                position = field.GetPosition();
                field.DoAction(this);
                return true;
            }else
                field = oldField;
        }else if(direction == Direction.DOWN)
            Die();
        return false;
    }


    /**
    *
    * @return number of keys that have not been collected so far
    */
    public int GetKeysCollected() {
        int tmp = keysCollected;
        keysCollected = 0;
        return tmp;
    }

    /**
    * Pick up a key.
    *
    * Note that this method is called from the key's own DoAction method,
    * which modifies the key's isCollected variable itself,
    * so there's no need to do that here.
    */
    public void PickUpKey() {
        ++keysCollected;
    }

    /**
    *
    * @return a reference to the current tile
    */
    public Tile GetTile() {
        return position.tile;
    }

    /**
    *
    * @param point The point where the stickman should be moved
    */
    public void SetPosition(Point point) {
        field.Leave();
        field = point.tile.GetField(point);
        position = point;
        field.DoAction(this);
    }

    public void Die(){
        SetPosition(revivePosition);
    }

    public Color GetColor() {
        return color;
    }

    public Point GetPosition() {
        return position;
    }
}
